//  OpenCVDLL.cpp
//
//  OpenCV Wrapper functions for Mayhem face detector
//
// (c) 2011 Microsoft Applied Sciences Group
// Author: Sven Kratz

#include "stdafx.h"
#include "OpenCVDLL.h"

/*
*   OpenCV face detector using Haar Cascades
*   Based on the example found on the OpenCV Wiki
*/
using namespace OpenCVDLL;


FaceDetector::FaceDetector(int width, int height)
{
	Debug::WriteLine("[FaceDetector(C++/CLI)]");
	fprintf(stderr, "FaceDetector::FaceDetector\n");
	first = true;

#ifdef DEBUG
	printf("Allocating image"); 
#endif
	CvSize imgSize = cvSize(width,height);
	currentImage = cvCreateImage(imgSize, 8,3);

#ifdef DEBUG
	printf("Loading Cascade XML File");
#endif
	 cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
	 if (cascade != 0)
	 {
		 // Allocate the memory storage
		storage = cvCreateMemStorage(0);
		initialized = true;
	 }
	 else
	 {
		 printf("Loading Cascade XML Failed");
		 initialized = false;
	 }
	 
}

FaceDetector::~FaceDetector()
{
	Debug::WriteLine("[~FaceDetector(C++/CLI)]");
	IplImage * cImg = currentImage ;
	IplImage * tmp = temp;
	CvMemStorage * str = storage; 

	cvReleaseImage(&cImg);
	cvReleaseImage(&tmp);
	cvClearMemStorage(str);
}

void FaceDetector::ProcessFrame(unsigned char * imageData, int * faceCoords, int  & numDetectedFaceCoords)
{
	fprintf(stderr, "FaceDetector::ProcessFrame\n");
	// TODO
	if (initialized)
	{
		currentImage->imageData = (char*) imageData;
		 // Create two points to represent the face locations
		CvPoint pt1, pt2;
		

		// Clear the memory storage which was used before
	    cvClearMemStorage( storage );

		CvSeq* faces;

		// There can be more than one face in an image. So create a growable sequence of faces.
        // Detect the objects and store them in the sequence
		try{
			faces = cvHaarDetectObjects( currentImage, cascade, storage,
                                            1.1, 2, CV_HAAR_DO_CANNY_PRUNING,
                                            cvSize(40, 40) );
		}
		catch ( System::Exception^ ex )
		{
			Debug::WriteLine("FaceDetector::ProcessFrame cvHaarDetectObjects Exception");
			Debug::WriteLine(ex);
			return;
		}

        // Loop the number of faces found.

		int fc_idx = 0;

        for(int i = 0; i < (faces ? faces->total : 0); i++ )
        {
           // Create a new rectangle for drawing the face
            CvRect* r = (CvRect*)cvGetSeqElem( faces, i );

            // Find the dimensions of the face,and scale it if necessary
            pt1.x = r->x;//*scale;
            pt2.x = (r->x+r->width);//*scale;
            pt1.y = r->y;//*scale;
            pt2.y = (r->y+r->height);//*scale;



#ifdef DEBUG
			printf("Face %d Bounding Box at: (%d,%d);(%d,%d)\n",i,pt1.x,pt1.y,pt2.x,pt2.y);
#endif

			// save coordinates in the output array

			faceCoords[fc_idx++] = pt1.x;
			faceCoords[fc_idx++] = pt1.y;
			faceCoords[fc_idx++] = pt2.x;
			faceCoords[fc_idx++] = pt2.y;


            // Draw the rectangle in the input image
            //cvRectangle( img, pt1, pt2, CV_RGB(255,0,0), 3, 8, 0 );
			 
        }

		// return length of output array for further processing in C#
		numDetectedFaceCoords = fc_idx;

	}
}


